#include    "threads.h"

Threads::Threads(size_t workers) : _valid(true), _can_add(true) {
	for (size_t i = 0; i < workers; ++i) {
		_workers.push(new std::thread(&Threads::__WorkerThread, this));
	}
}

Threads::~Threads() {
	{
		std::unique_lock<std::mutex> _(_lock);
		_valid = false;
		_can_add = false;

		while (!_jobs.empty()) {
			IThreadJob * job = _jobs.front();
			_jobs.pop();
			delete job;
		}
	}

	_signal.notify_all();

	while (!_workers.empty()) {
		std::thread * p = _workers.front();
		_workers.pop();
		if (p->joinable()) p->join();
		delete p;
	}
}

void Threads::Wait() {
	{
		std::unique_lock<std::mutex> _(_lock);
		_can_add = false;
	}

	while (!_jobs.empty()) std::this_thread::sleep_for(std::chrono::milliseconds(1));

	{
		std::unique_lock<std::mutex> _(_lock);
		_can_add = true;
	}
}

void Threads::__WorkerThread() {
	while (true) {
		std::unique_lock<std::mutex> _(_lock);
		if (!_valid) break;
		if (_jobs.empty()) _signal.wait(_);
		if (_jobs.empty()) continue;

		IThreadJob * job = _jobs.front();
		_jobs.pop();
		_.unlock();

		job->OnRun();
		delete job;
	}
}